﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Web.UI.WebControls;

namespace FRL.DebtChased.Website
{

	/// <summary>
	/// Declaration of HtmlTableBuilder class
	/// Class for generating table html from column and row data
	/// </summary>
	public class HtmlTableBuilder
	{

		/////////////////////////////////////////////////////////////
		// Nested classes

		private class Cell
		{

			/////////////////////////////////////////////////////////////
			// Attributes

			private int m_iColumn;
			public int Column
			{
				get { return m_iColumn; }
			}

			private int m_iRow;
			public int Row
			{
				get { return m_iRow; }
			}

			private string m_strValue;
			public string Value
			{
				get { return m_strValue; }
				set { m_strValue = value; }
			}

			private bool m_bBold;
			public bool Bold
			{
				get { return m_bBold; }
				set { m_bBold = value; }
			}

			private bool m_bNoWrap;
			public bool NoWrap
			{
				get { return m_bNoWrap; }
				set { m_bNoWrap = value; }
			}

			private string m_strStyle;
			public string Style
			{
				get { return m_strStyle; }
				set { m_strStyle = value; }
			}

			private HorizontalAlign m_horzAlign = HorizontalAlign.NotSet;
			public HorizontalAlign HorzAlign
			{
				get { return m_horzAlign; }
				set { m_horzAlign = value; }
			}

			/////////////////////////////////////////////////////////////
			// Construction

			public Cell(int iColumn, int iRow, string strValue)
			{

				// Initialize member variables
				m_iColumn = iColumn;
				m_iRow = iRow;
				m_strValue = strValue;

			}

		}

		/////////////////////////////////////////////////////////////
		// Attributes

		private List<Cell> m_cells = new List<Cell>();

		private string m_strTableId;
		private int m_iCellSpacing;
		private int m_iCellPadding;
		private int m_iTableWidth;
		private int m_iTableHeight;
		private string m_strTableStyle;

		private int m_iBorder = 0;
		public int Border
		{
			get { return m_iBorder; }
			set { m_iBorder = value; }
		}

		private HorizontalAlign m_HorzAlign = HorizontalAlign.NotSet;
		public HorizontalAlign HorzAlign
		{
			get { return m_HorzAlign; }
			set { m_HorzAlign = value; }
		}

		private VerticalAlign m_VertAlign = VerticalAlign.NotSet;
		public VerticalAlign VertAlign
		{
			get { return m_VertAlign; }
			set { m_VertAlign = value; }
		}

		/////////////////////////////////////////////////////////////
		// Construction

		public HtmlTableBuilder( string strTableId, int iCellSpacing, int iCellPadding, int iBorder, int iTableWidth, int iTableHeight, string strTableStyle )
		{

			// Initialize member variables
			m_strTableId = strTableId;
			m_iCellSpacing = iCellSpacing;
			m_iCellPadding = iCellPadding;
			m_iBorder = iBorder;
			m_iTableWidth = iTableWidth;
			m_iTableHeight = iTableHeight;
			m_strTableStyle = strTableStyle;

		}

		/////////////////////////////////////////////////////////////
		// Operations

		private int _calcColumns()
		{

			// declare return variable
			int iFtmp = 0;

			// Loop through cells
			for (int i1 = 0; i1 < m_cells.Count; i1++)
				iFtmp = Math.Max(iFtmp, m_cells[i1].Column + 1);

			// return variable
			return iFtmp;

		}

		private int _calcRows()
		{

			// declare return variable
			int iFtmp = 0;

			// Loop through cells
			for (int i1 = 0; i1 < m_cells.Count; i1++)
				iFtmp = Math.Max(iFtmp, m_cells[i1].Row + 1);

			// return variable
			return iFtmp;

		}

		private Cell _findCell(int iColumn, int iRow)
		{

			// Declare return variable
			return (from c in m_cells where (c.Row == iRow) && (c.Column == iColumn) select c).FirstOrDefault();

		}

		public void SetCell(int iColumn, int iRow, string strValue )
		{

			// Replace -1 with new cell indexes
			if (iColumn == -1)
				iColumn = _calcColumns();
			if (iRow == -1)
				iRow = _calcRows();

			// Find an existing cell
			Cell cell = _findCell(iColumn, iRow);
			if (cell == null)
				m_cells.Add(new Cell(iColumn, iRow, strValue));
			else
				cell.Value = strValue;

		}

		public void SetCells(int iColumn, int iRow, params string[] strValues)
		{

			// Replace -1 with new cell indexes
			if (iColumn == -1)
				iColumn = _calcColumns();
			if (iRow == -1)
				iRow = _calcRows();

			// Loop through values
			for(int i1=0; i1<strValues.Length; i1++ )
				this.SetCell(iColumn+i1,iRow,strValues[i1]);

		}

		public void SetBold(int iColumn0, int iRow0, int iColumn1, int iRow1 )
		{

			// Loop through columns
			for( int iColumn=iColumn0; iColumn<=iColumn1; iColumn++ )
				for( int iRow=iRow0; iRow<=iRow1; iRow++ )
				{
					Cell cell = _findCell(iColumn,iRow);
					if(cell!=null)
						cell.Bold = true;
				}
		}

		public void SetNoWrap()
		{

			// Loop through all cells
			for(int i1=0; i1<m_cells.Count; i1++ )
				m_cells[i1].NoWrap = true;

		}

		public void SetStyle(int iColumn0, int iRow0, int iColumn1, int iRow1, string strStyle)
		{

			// Replace -1 with new cell indexes
			if (iColumn1 == -1)
				iColumn1 = _calcColumns();
			if (iRow1 == -1)
				iRow1 = _calcRows();

			// Loop through columns
			for (int iColumn = iColumn0; iColumn <= iColumn1; iColumn++)
				for (int iRow = iRow0; iRow <= iRow1; iRow++)
				{
					Cell cell = _findCell(iColumn, iRow);
					if (cell != null)
						cell.Style = strStyle;
				}

		}

		public void SetCellAlign(int iColumn0, int iRow0, int iColumn1, int iRow1, HorizontalAlign horzAlign)
		{

			// Replace -1 with new cell indexes
			if (iColumn1 == -1)
				iColumn1 = _calcColumns();
			if (iRow1 == -1)
				iRow1 = _calcRows();

			// Loop through columns
			for (int iColumn = iColumn0; iColumn <= iColumn1; iColumn++)
				for (int iRow = iRow0; iRow <= iRow1; iRow++)
				{
					Cell cell = _findCell(iColumn, iRow);
					if (cell != null)
						cell.HorzAlign = horzAlign;
				}

		}

		public string ToHtml()
		{

			// Generate HTML markup
			StringBuilder sb = new StringBuilder();

			// Add table heading
			sb.AppendFormat("<table id=\"{0}\" cellspacing=\"{1}\" cellpadding=\"{2}\" border=\"{3}\"",
				m_strTableId,
				m_iCellSpacing,
				m_iCellPadding,
				m_iBorder
			);
			if (m_HorzAlign != HorizontalAlign.NotSet)
				sb.AppendFormat(" align=\"{0}\"", _getHtmlAlignString(m_HorzAlign));
			if (m_VertAlign != VerticalAlign.NotSet)
				sb.AppendFormat(" align=\"{0}\"", _getHtmlAlignString(m_VertAlign));
			if ((m_iTableWidth != 0) || (m_iTableHeight != 0))
			{
				sb.Append(" style=\"");
				if (m_iTableWidth != 0)
					sb.AppendFormat(" width:{0}px;", m_iTableWidth);
				if (m_iTableHeight != 0)
					sb.AppendFormat(" height:{0}px;", m_iTableHeight);
				sb.Append(" \"");
			}
			if(!string.IsNullOrEmpty(m_strTableStyle))
				sb.AppendFormat(" class=\"{0}\"", m_strTableStyle);				
			sb.Append(" >");

			// Calculate rows and columns
			int iColumns = _calcColumns();
			int iRows = _calcRows();
			for (int iRow = 0; iRow < iRows; iRow++)
			{

				// Add row heading
				sb.Append("<tr>");

				// Loop through columns
				for (int iColumn = 0; iColumn < iColumns; iColumn++)
				{

					// Find the cell
					Cell cell = _findCell(iColumn, iRow);

					// If no cell found...
					if(cell==null)
						sb.Append("<td></td>");
					else
					{

						// Add column
						sb.Append("<td");
						if(!string.IsNullOrEmpty(cell.Style))
							sb.AppendFormat(" class=\"{0}\"", cell.Style);
						if(cell.NoWrap)
							sb.Append(" nowrap=\"nowrap\"");

						if (cell.HorzAlign != HorizontalAlign.NotSet)
							sb.AppendFormat(" align=\"{0}\"",_getHtmlAlignString(cell.HorzAlign));
						sb.Append(" >");
						if (cell != null)
						{
							if (cell.Bold)
								sb.Append("<strong>");
							sb.Append(cell.Value);
							if (cell.Bold)
								sb.Append("</strong>");
						}
						sb.Append("</td>");

					}

				}

				// Add row footer
				sb.Append("</tr>");

			}

			// Add table footer
			sb.Append("</table>");

			// Return string
			return sb.ToString();

		}

		// Static helper functions

		private static string _getHtmlAlignString(HorizontalAlign horzAlign)
		{

			// Declare return variable
			string strFtmp = null;

			// compare values
			switch (horzAlign)
			{
				case HorizontalAlign.Left:
					strFtmp = "left";
					break;
				case HorizontalAlign.Center:
					strFtmp = "center";
					break;
				case HorizontalAlign.Right:
					strFtmp = "right";
					break;
			} // switch

			// Return variable
			return strFtmp;

		}

		private static string _getHtmlAlignString(VerticalAlign vertAlign)
		{

			// Declare return variable
			string strFtmp = null;

			// compare values
			switch (vertAlign)
			{
				case VerticalAlign.Bottom:
					strFtmp = "bottom";
					break;
				case VerticalAlign.Middle:
					strFtmp = "center";
					break;
				case VerticalAlign.Top:
					strFtmp = "top";
					break;
			} // switch

			// Return variable
			return strFtmp;

		}

	}

}